#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
#include <QDateTime>
#include <QInputDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_rng(std::random_device{}())  // 初始化随机数生成器
{
    ui->setupUi(this);

    // 初始化随机数生成器
    m_startTime = QTime::currentTime();  // 记录程序启动时间

    // 初始化曲线
    ui->customPlot->addGraph(); // 添加曲线0
    ui->customPlot->graph(0)->setPen(QPen(QColor(40, 110, 255)));  // 设置曲线颜色

    ui->customPlot->addGraph(); // 添加曲线1
    ui->customPlot->graph(1)->setPen(QPen(QColor(255, 110, 40)));  // 设置曲线颜色

    // 添加更多曲线...
    for (int i = 2; i <= 10; i++) {
        ui->customPlot->addGraph();
        // 设置不同颜色
        int r = 40 + (i * 20) % 216;
        int g = 110 + (i * 10) % 216;
        int b = 255 - (i * 20) % 216;
        QColor color(r, g, b);
        ui->customPlot->graph(i)->setPen(QPen(color));
    }

    // 设置 x 轴为时间格式
    QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
    timeTicker->setTimeFormat("%h:%m:%s");
    ui->customPlot->xAxis->setTicker(timeTicker);
    ui->customPlot->axisRect()->setupFullAxesBox();
    ui->customPlot->yAxis->setRange(-1.2, 1.2);  // 设置Y轴范围

    // 交互设置
    ui->customPlot->setInteraction(QCP::iRangeDrag, true);  // 启用范围拖拽
    ui->customPlot->axisRect()->setRangeDrag(Qt::Vertical | Qt::Horizontal);
    ui->customPlot->axisRect()->setRangeDragAxes(ui->customPlot->xAxis, ui->customPlot->yAxis);
    ui->customPlot->setInteraction(QCP::iRangeZoom, true);  // 启用范围缩放
    ui->customPlot->axisRect()->setRangeZoom(Qt::Vertical | Qt::Horizontal);
    ui->customPlot->axisRect()->setRangeZoomAxes(ui->customPlot->xAxis, ui->customPlot->yAxis);
    ui->customPlot->setInteraction(QCP::iSelectPlottables, true);  // 启用选择曲线

    // 连接坐标轴范围变化信号
    connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->xAxis2, SLOT(setRange(QCPRange)));
    connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->yAxis2, SLOT(setRange(QCPRange)));

    // 连接用户交互信号
    connect(ui->customPlot, &QCustomPlot::mousePress, [this]() {
        m_userInteracting = true;
        autoUpdateTimer.stop();  // 用户交互时停止自动更新
    });

    connect(ui->customPlot, &QCustomPlot::mouseRelease, [this]() {
        autoUpdateTimer.start(2000);  // 2秒后恢复自动更新
    });

    connect(ui->customPlot, &QCustomPlot::mouseWheel, [this]() {
        m_userInteracting = true;
        autoUpdateTimer.stop();
        autoUpdateTimer.start(2000);  // 2秒后恢复自动更新
    });

    // 连接鼠标移动信号
    connect(ui->customPlot, &QCustomPlot::mouseMove, this, &MainWindow::onMouseMove);

    // 自动更新定时器
    connect(&autoUpdateTimer, &QTimer::timeout, this, &MainWindow::onAutoUpdateTimer);

    // 数据更新定时器
    connect(&dataTimer, &QTimer::timeout, this, &MainWindow::realtimeDataSlot);
    dataTimer.start(20);  // 50FPS

    // 初始中心点
    m_xCenter = ui->customPlot->xAxis->range().center();
    m_yCenter = ui->customPlot->yAxis->range().center();

    // ====================== 创建控制按钮 ======================
    int buttonY = 550;
    int buttonX = 20;
    int buttonWidth = 80;
    int buttonHeight = 30;
    int buttonSpacing = 10;

    connect(ui->pauseButton, &QPushButton::clicked, this, &MainWindow::onPauseButtonClicked);
    buttonX += buttonWidth + buttonSpacing;

    connect(ui->screenshotButton, &QPushButton::clicked, this, &MainWindow::onScreenshotButtonClicked);
    buttonX += buttonWidth + buttonSpacing;

    connect(ui->timeMarkerButton, &QPushButton::clicked, this, &MainWindow::onAddTimeMarkerClicked);
    buttonX += buttonWidth + buttonSpacing;

    connect(ui->exportButton, &QPushButton::clicked, this, &MainWindow::onExportDataClicked);
    buttonX += buttonWidth + buttonSpacing;

    // 清除标记按钮
    connect(ui->clearMarkersButton, &QPushButton::clicked, this, &MainWindow::onClearMarkersClicked);
    buttonX += buttonWidth + buttonSpacing;

    // ====================== 创建缩放和拖拽控件 ======================
    int controlY = 500;
    int labelWidth = 70;

    // X轴缩放
    ui->dialZoomX->setRange(1, 100);
    ui->dialZoomX->setValue(50);
    connect(ui->dialZoomX, &QDial::valueChanged, this, &MainWindow::onZoomXChanged);

    // Y轴缩放
    ui->dialZoomY->setRange(1, 100);
    ui->dialZoomY->setValue(50);
    connect(ui->dialZoomY, &QDial::valueChanged, this, &MainWindow::onZoomYChanged);

    // X轴拖拽
    ui->sliderPanX->setRange(-100, 100);
    ui->sliderPanX->setValue(0);
    connect(ui->sliderPanX, &QSlider::valueChanged, this, &MainWindow::onPanXChanged);
    connect(ui->sliderPanX, &QSlider::sliderReleased, this, &MainWindow::onPanXSliderReleased);

    // Y轴拖拽
    ui->sliderPanY->setRange(-100, 100);
    ui->sliderPanY->setValue(0);
    connect(ui->sliderPanY, &QSlider::valueChanged, this, &MainWindow::onPanYChanged);
    connect(ui->sliderPanY, &QSlider::sliderReleased, this, &MainWindow::onPanYSliderReleased);

    // ====================== 创建鼠标悬停显示组件 ======================
    // 1. 创建垂直线和水平线
    m_vLine = new QCPItemLine(ui->customPlot);
    m_hLine = new QCPItemLine(ui->customPlot);

    // 2. 创建值跟踪点和标签
    m_valueTracer = new QCPItemTracer(ui->customPlot);
    m_valueLabel = new QCPItemText(ui->customPlot);

    // 3. 设置样式
    m_vLine->setPen(QPen(Qt::gray, 1, Qt::DashLine));
    m_hLine->setPen(QPen(Qt::gray, 1, Qt::DashLine));

    m_valueTracer->setStyle(QCPItemTracer::tsCircle);
    m_valueTracer->setSize(8);
    m_valueTracer->setPen(QPen(Qt::red, 2));
    m_valueTracer->setBrush(Qt::white);

    m_valueLabel->setPositionAlignment(Qt::AlignLeft|Qt::AlignTop);
    m_valueLabel->position->setParentAnchor(m_valueTracer->position);
    m_valueLabel->position->setCoords(10, -10);  // 偏移量
    m_valueLabel->setTextAlignment(Qt::AlignLeft);
    m_valueLabel->setPen(QPen(Qt::black));
    m_valueLabel->setBrush(QBrush(QColor(255, 255, 255, 200)));
    m_valueLabel->setPadding(QMargins(5, 2, 5, 2));

    // 4. 初始隐藏
    m_vLine->setVisible(false);
    m_hLine->setVisible(false);
    m_valueTracer->setVisible(false);
    m_valueLabel->setVisible(false);

    // 启用鼠标跟踪
    ui->customPlot->setMouseTracking(true);

    // 设置初始状态栏消息
    statusBar()->showMessage("程序已启动，等待数据...", 3000);
}


// X轴缩放控制
void MainWindow::onZoomXChanged(int value)
{
    // 计算缩放因子 (1-100 映射到 0.1-10.0)
    m_xZoomFactor = 0.1 + (value / 100.0) * 9.9;

    // 更新X轴范围
    double newRange = m_xRange / m_xZoomFactor;
    ui->customPlot->xAxis->setRange(m_xCenter - newRange/2, m_xCenter + newRange/2);

    ui->customPlot->replot();  // 重新绘制图表

    // 更新状态栏
    statusBar()->showMessage(QString("X轴缩放: %1x").arg(m_xZoomFactor, 0, 'f', 1), 1000);
}

// Y轴缩放控制
void MainWindow::onZoomYChanged(int value)
{
    m_yZoomFactor = 0.1 + (value / 100.0) * 9.9;

    double newRange = m_yRange / m_yZoomFactor;
    ui->customPlot->yAxis->setRange(m_yCenter - newRange/2, m_yCenter + newRange/2);

    ui->customPlot->replot();  // 重新绘制图表

    // 更新状态栏
    statusBar()->showMessage(QString("Y轴缩放: %1x").arg(m_yZoomFactor, 0, 'f', 1), 1000);
}

// X轴拖拽控制 - 双向
void MainWindow::onPanXChanged(int value)
{
    m_userInteracting = true;
    autoUpdateTimer.stop();  // 停止自动更新

    static int lastValue = 0;  // 上一次的滑块值
    int delta = value - lastValue;  // 当前值与上一次值的差
    lastValue = value;  // 更新上一次的滑块值

    double currentRange = ui->customPlot->xAxis->range().size();  // 当前 X 轴的范围大小
    double offset = delta * currentRange * 0.001;  // 计算偏移量，0.001 是缩放因子

    m_xPanAccumulator += offset;

    QCPRange currentRangeObj = ui->customPlot->xAxis->range();  // 获取当前 X 轴的范围
    ui->customPlot->xAxis->setRange(currentRangeObj.lower + offset, currentRangeObj.upper + offset);

    ui->customPlot->replot();  // 重新绘制图表
}

// Y轴拖拽控制 - 双向
void MainWindow::onPanYChanged(int value)
{
    m_userInteracting = true;
    autoUpdateTimer.stop();  // 停止自动更新

    static int lastValue = 0;  // 上一次的滑块值
    int delta = value - lastValue;  // 当前值与上一次值的差
    lastValue = value;  // 更新上一次的滑块值

    double currentRange = ui->customPlot->yAxis->range().size();  // 当前 Y 轴的范围大小
    double offset = delta * currentRange * 0.001;  // 计算偏移量，0.001 是缩放因子

    m_yPanAccumulator += offset;

    QCPRange currentRangeObj = ui->customPlot->yAxis->range();  // 获取当前 Y 轴的范围
    ui->customPlot->yAxis->setRange(currentRangeObj.lower + offset, currentRangeObj.upper + offset);

    ui->customPlot->replot();  // 重新绘制图表
}

// X轴滑块释放
void MainWindow::onPanXSliderReleased()
{
    // 重置滑块位置
    ui->sliderPanX->setValue(0);

    // 更新中心点
    m_xCenter = ui->customPlot->xAxis->range().center();

    // 重置累计偏移
    m_xPanAccumulator = 0;

    // 标记需要更新范围
    m_userInteracting = false;
    autoUpdateTimer.start(100);  // 立即触发更新
}

// Y轴滑块释放
void MainWindow::onPanYSliderReleased()
{
    // 重置滑块位置
    ui->sliderPanY->setValue(0);

    // 更新中心点
    m_yCenter = ui->customPlot->yAxis->range().center();

    // 重置累计偏移
    m_yPanAccumulator = 0;

    // 标记需要更新范围
    m_userInteracting = false;
    autoUpdateTimer.start(100);  // 立即触发更新
}

// 自动更新定时器处理
void MainWindow::onAutoUpdateTimer()
{
    // 停止定时器
    autoUpdateTimer.stop();

    // 重置交互状态
    m_userInteracting = false;
}

// 鼠标移动事件处理 - 显示值
void MainWindow::onMouseMove(QMouseEvent* event)
{
    // 获取鼠标位置对应的坐标
    double x = ui->customPlot->xAxis->pixelToCoord(event->pos().x());
    double y = ui->customPlot->yAxis->pixelToCoord(event->pos().y());

    // 设置垂直线位置
    m_vLine->start->setCoords(x, ui->customPlot->yAxis->range().lower);
    m_vLine->end->setCoords(x, ui->customPlot->yAxis->range().upper);

    // 设置水平线位置
    m_hLine->start->setCoords(ui->customPlot->xAxis->range().lower, y);
    m_hLine->end->setCoords(ui->customPlot->xAxis->range().upper, y);

    // 查找最近的曲线点
    double minDistance = std::numeric_limits<double>::max();
    int closestGraph = -1;
    QPointF closestPoint;

    for (int i = 0; i <= 10; i++) {
        QCPGraph* graph = ui->customPlot->graph(i);
        if (!graph || graph->data()->isEmpty()) continue;

        // 找到鼠标 X 坐标附近的数据点
        auto it = graph->data()->findBegin(x);
        if (it == graph->data()->end()) continue;

        // 检查前后两个点
        auto prev = (it != graph->data()->begin()) ? it - 1 : it;
        auto next = it;

        // 计算距离
        double distPrev = qAbs(prev->key - x);
        double distNext = qAbs(next->key - x);

        // 选择更近的点
        auto closest = (distPrev < distNext) ? prev : next;

        // 计算像素距离
        double px = ui->customPlot->xAxis->coordToPixel(closest->key);
        double py = ui->customPlot->yAxis->coordToPixel(closest->value);
        double distance = QPointF(event->pos() - QPointF(px, py)).manhattanLength();

        if (distance < minDistance) {
            minDistance = distance;
            closestGraph = i;
            closestPoint = QPointF(closest->key, closest->value);
        }
    }

    // 如果找到最近点，显示值
    if (closestGraph >= 0 && minDistance < 30) {  // 30 像素范围内
        m_valueTracer->setGraph(ui->customPlot->graph(closestGraph));
        m_valueTracer->setGraphKey(closestPoint.x());
        m_valueLabel->setText(QString("曲线 %1\nX: %2\nY: %3")
                              .arg(closestGraph)
                              .arg(closestPoint.x(), 0, 'f', 3)
                              .arg(closestPoint.y(), 0, 'f', 3));

        // 显示组件
        m_vLine->setVisible(true);
        m_hLine->setVisible(true);
        m_valueTracer->setVisible(true);
        m_valueLabel->setVisible(true);
    } else {
        // 隐藏组件
        m_vLine->setVisible(false);
        m_hLine->setVisible(false);
        m_valueTracer->setVisible(false);
        m_valueLabel->setVisible(false);
    }

    ui->customPlot->replot();
}

// 暂停按钮点击事件
void MainWindow::onPauseButtonClicked()
{
    // 切换暂停状态
    m_paused = !m_paused;

    // 更新按钮文本
    QPushButton *btn = qobject_cast<QPushButton*>(sender());
    if (btn) {
        btn->setText(m_paused ? "继续" : "暂停");
    }

    // 暂停时，设置用户交互状态为 true，阻止自动滚动
    if (m_paused) {
        m_userInteracting = true;
        statusBar()->showMessage("已暂停数据滚动", 2000);
    } else {
        // 恢复时，重置交互状态
        m_userInteracting = false;

        // 更新中心点为当前视图中心
        m_xCenter = ui->customPlot->xAxis->range().center();
        m_yCenter = ui->customPlot->yAxis->range().center();

        // 强制刷新视图
        realtimeDataSlot();
        statusBar()->showMessage("已恢复数据滚动", 2000);
    }
}

// 截图按钮点击事件
void MainWindow::onScreenshotButtonClicked()
{
    // 生成文件名：截图_年月日_时分秒.png
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "保存截图",
        QString("screenshot_%1.png").arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")),
        "PNG图片 (*.png);;所有文件 (*)"
    );

    if (!fileName.isEmpty()) {
        // 添加时间标记到截图
        onAddTimeMarkerClicked();
        ui->customPlot->replot();

        // 保存截图
        bool success = ui->customPlot->savePng(fileName, 0, 0, 2.0);  // 2 倍分辨率

        if (success) {
            statusBar()->showMessage("截图已保存: " + fileName, 3000);
        } else {
            QMessageBox::warning(this, "保存失败", "无法保存截图到: " + fileName);
        }
    }
}

// 添加时间标记
void MainWindow::onAddTimeMarkerClicked()
{
    // 获取当前时间
    QString timeStr = QDateTime::currentDateTime().toString("hh:mm:ss");

    // 创建时间标记文本
    QCPItemText *timeMarker = new QCPItemText(ui->customPlot);

    // 设置文本
    timeMarker->setText(timeStr);
    timeMarker->setFont(QFont("Arial", 10, QFont::Bold));
    timeMarker->setColor(Qt::red);
    timeMarker->setPositionAlignment(Qt::AlignRight|Qt::AlignTop);

    // 设置位置（图表右上角）
    timeMarker->position->setType(QCPItemPosition::ptAxisRectRatio);
    timeMarker->position->setCoords(0.98, 0.02);

    // 添加背景
    timeMarker->setBrush(QBrush(QColor(255, 255, 255, 180)));
    timeMarker->setPen(QPen(Qt::red));
    timeMarker->setPadding(QMargins(5, 2, 5, 2));

    // 保存到列表
    m_timeMarkers.append(timeMarker);

    // 刷新图表
    ui->customPlot->replot();

    statusBar()->showMessage("已添加时间标记: " + timeStr, 2000);
}

// 清除所有标记
void MainWindow::onClearMarkersClicked()
{
    for (QCPItemText* marker : m_timeMarkers) {
        ui->customPlot->removeItem(marker);
        delete marker;
    }
    m_timeMarkers.clear();
    ui->customPlot->replot();
    statusBar()->showMessage("已清除所有时间标记", 2000);
}

// 导出数据
void MainWindow::onExportDataClicked()
{
    // 获取保存文件名
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "导出数据",
        QString("data_export_%1.csv").arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")),
        "CSV文件 (*.csv);;所有文件 (*)"
    );

    if (fileName.isEmpty()) return;

    // 打开文件
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "导出失败", "无法打开文件进行写入: " + fileName);
        return;
    }

    QTextStream out(&file);
    out.setRealNumberPrecision(6);  // 设置精度

    // 写入CSV表头
    out << "Time (s)";
    for (int i = 0; i <= 10; i++) {
        out << ",Graph " << i;
    }
    out << "\n";

    // 获取所有数据点的时间范围
    double minTime = std::numeric_limits<double>::max();
    double maxTime = std::numeric_limits<double>::lowest();

    for (int i = 0; i <= 10; i++) {
        if (ui->customPlot->graph(i)->data()->isEmpty()) continue;

        double firstKey = ui->customPlot->graph(i)->data()->begin()->key;
        double lastKey = (ui->customPlot->graph(i)->data()->end()-1)->key;

        minTime = qMin(minTime, firstKey);
        maxTime = qMax(maxTime, lastKey);
    }

    // 如果时间范围无效，使用默认值
    if (minTime >= maxTime) {
        minTime = 0;
        maxTime = 10;
    }

    // 设置时间步长（1000点）
    double timeStep = (maxTime - minTime) / 1000.0;
    if (timeStep <= 0) timeStep = 0.01;

    // 导出数据（按时间对齐）
    int rowCount = 0;
    for (double t = minTime; t <= maxTime; t += timeStep) {
        out << t;

        for (int i = 0; i <= 10; i++) {
            double value = std::numeric_limits<double>::quiet_NaN();

            // 如果图表有数据，查找最近的点
            if (!ui->customPlot->graph(i)->data()->isEmpty()) {
                auto it = ui->customPlot->graph(i)->data()->findBegin(t);
                if (it != ui->customPlot->graph(i)->data()->end()) {
                    // 线性插值
                    auto next = it;
                    auto prev = (it != ui->customPlot->graph(i)->data()->begin()) ? it - 1 : it;

                    if (next != prev && next->key != prev->key) {
                        double ratio = (t - prev->key) / (next->key - prev->key);
                        value = prev->value + ratio * (next->value - prev->value);
                    } else {
                        value = it->value;
                    }
                }
            }

            out << "," << value;
        }

        out << "\n";
        rowCount++;
    }

    file.close();

    // 添加时间标记
    onAddTimeMarkerClicked();

    statusBar()->showMessage(QString("数据已导出: %1 (%2 行)").arg(fileName).arg(rowCount), 5000);
}

// 实时数据更新
void MainWindow::realtimeDataSlot()
{
    double elapsed = m_startTime.elapsed() / 1000.0;  // 程序运行时间（秒）
    static double lastPointKey = 0;

    // 每20ms添加一次数据
    if (elapsed - lastPointKey > 0.02) {
        // 生成随机数据
        std::uniform_real_distribution<double> dist(-0.5, 0.5);

        for (int i = 0; i <= 10; i++) {
            double baseValue = 0;

            if (i % 3 == 0) {
                baseValue = sin(elapsed * (1.0 + i * 0.1));
            } else if (i % 3 == 1) {
                baseValue = cos(elapsed * (0.8 + i * 0.1));
            } else {
                baseValue = sin(elapsed * (1.2 + i * 0.1)) * cos(elapsed * (0.7 + i * 0.1));
            }

            // 添加噪声
            double noise = dist(m_rng) * (0.2 + i * 0.05);
            double value = baseValue * (0.8 + i * 0.02) + noise;

            // 添加数据点
            ui->customPlot->graph(i)->addData(elapsed, value);

            // 限制数据点数量（性能优化）
            if (ui->customPlot->graph(i)->data()->size() > 1000) {
                ui->customPlot->graph(i)->data()->removeBefore(elapsed - 10);
            }
        }

        lastPointKey = elapsed;
    }

    // 仅当用户未交互且未暂停时自动更新范围
    if (!m_userInteracting && !m_paused) {
        // 更新X轴范围（考虑缩放因子）
        double xRange = 8.0 / m_xZoomFactor;
        ui->customPlot->xAxis->setRange(elapsed - xRange, elapsed);

        // 更新Y轴范围（考虑缩放因子）
        double yRange = 2.4 / m_yZoomFactor;
        ui->customPlot->yAxis->setRange(m_yCenter - yRange/2, m_yCenter + yRange/2);

        // 更新中心点
        m_xCenter = ui->customPlot->xAxis->range().center();
    }

    ui->customPlot->replot();

    // FPS计算
    static double lastFpsKey = 0;
    static int frameCount = 0;
    frameCount++;

    if (elapsed - lastFpsKey > 2.0) {
        double fps = frameCount / (elapsed - lastFpsKey);
        int totalPoints = 0;
        for (int i = 0; i <= 10; i++) {
            totalPoints += ui->customPlot->graph(i)->data()->size();
        }

        statusBar()->showMessage(
            QString("%1 FPS, 总数据点: %2%3")
            .arg(fps, 0, 'f', 0)
            .arg(totalPoints)
            .arg(m_paused ? " [已暂停]" : ""),  // 暂停状态显示
            0);

        lastFpsKey = elapsed;
        frameCount = 0;
    }
}

// 析构函数
MainWindow::~MainWindow()
{
    delete ui;
}
